using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Spine;
using Spine.Unity;
using Spine.Unity.AttachmentTools;

public class SpineManager : MonoBehaviour
{
    void Start()
    {
        //方式1
        sourceMaterial = skeletonAnimation1.SkeletonDataAsset.atlasAssets[0].PrimaryMaterial;
        equipsSkin = new Skin("Equips");
        var templateSkin = skeletonAnimation1.Skeleton.Data.FindSkin("default");
        if (templateSkin != null) equipsSkin.AddAttachments(templateSkin);
        skeletonAnimation1.Skeleton.Skin = equipsSkin;
        RefreshSkeletonAttachments();

        //方式2
        skeletonAnimation2.initialSkinName = _initSkinName;
        skeletonAnimation2.Initialize(true);
        _skeleton2 = skeletonAnimation2.Skeleton;
    }

    void Update()
    {
        // 通过单个图片的方式换装
        if (Input.GetKeyDown(KeyCode.A)) ChangeBySprite(headSp, SlotName.Head);
        else if (Input.GetKeyDown(KeyCode.S)) ChangeBySprite(bodySp, SlotName.Body);
        else if (Input.GetKeyDown(KeyCode.D)) ChangeBySprite(neckSp, SlotName.Neck);
        else if (Input.GetKeyDown(KeyCode.F)) ChangeBySprite(weaponSp, SlotName.Weapon);


        //通过皮肤的方式换装
        if (Input.GetKeyDown(KeyCode.Q)) ChangeBySkin(SlotName.Head);
        else if (Input.GetKeyDown(KeyCode.W)) ChangeBySkin(SlotName.Body);
        else if (Input.GetKeyDown(KeyCode.E)) ChangeBySkin(SlotName.Neck);
        else if (Input.GetKeyDown(KeyCode.R)) ChangeBySkin(SlotName.Arm_Left);
        else if (Input.GetKeyDown(KeyCode.T)) ChangeBySkin(SlotName.Weapon);
    }

    #region 通过单个图片的方式换装
    public SkeletonAnimation skeletonAnimation1;
    private Material sourceMaterial;
    public bool applyPMA = true;

    private Skin equipsSkin;
    private Skin collectedSkin;

    private Material runtimeMaterial;
    private Texture2D runtimeAtlas;

    public Sprite headSp;
    public Sprite bodySp;
    public Sprite neckSp;
    public Sprite weaponSp;
    private void ChangeBySprite(Sprite sprite, string slotName)
    {
        var skeletonData = skeletonAnimation1.skeleton.Data;
        int slotIndex = skeletonData.FindSlotIndex(slotName);
        Skin templateSkin = skeletonData.FindSkin("default");
        Attachment templateAttachment = templateSkin.GetAttachment(slotIndex, slotName);
        Attachment attachment = templateAttachment.GetRemappedClone(sprite, sourceMaterial, premultiplyAlpha: this.applyPMA);
        Equip(slotIndex, slotName, attachment);
    }

    // 换装
    public void Equip(int slotIndex, string attachmentName, Attachment attachment)
    {
        equipsSkin.SetAttachment(slotIndex, attachmentName, attachment);
        skeletonAnimation1.Skeleton.SetSkin(equipsSkin);
        RefreshSkeletonAttachments();
        OptimizeSkin();
    }

    // 重置皮肤并且合并材质
    public void OptimizeSkin()
    {
        // 1. Collect all the attachments of all active skins.
        collectedSkin = collectedSkin ?? new Skin("Collected skin");
        collectedSkin.Clear();
        collectedSkin.AddAttachments(skeletonAnimation1.Skeleton.Data.DefaultSkin);
        collectedSkin.AddAttachments(equipsSkin);

        // 2. Create a repacked skin.
        // Note: materials and textures returned by GetRepackedSkin() behave like 'new Texture2D()' and need to be destroyed
        if (runtimeMaterial)
            Destroy(runtimeMaterial);
        if (runtimeAtlas)
            Destroy(runtimeAtlas);
        var repackedSkin = collectedSkin.GetRepackedSkin("Repacked skin", sourceMaterial,
            out runtimeMaterial, out runtimeAtlas, maxAtlasSize: 1024, clearCache: false);
        collectedSkin.Clear();

        // You can optionally clear the textures cache after each ore multiple repack operations are done.
        // AtlasUtilities.ClearCache();
        // Resources.UnloadUnusedAssets();

        // 3. Use the repacked skin.
        skeletonAnimation1.Skeleton.Skin = repackedSkin;
        RefreshSkeletonAttachments();
    }

    private void RefreshSkeletonAttachments()
    {
        skeletonAnimation1.Skeleton.SetSlotsToSetupPose();
        skeletonAnimation1.AnimationState.Apply(skeletonAnimation1.Skeleton); //skeletonAnimation.Update(0);
    }
    #endregion



    #region 通过皮肤的方式换装
    public SkeletonAnimation skeletonAnimation2;
    private Skeleton _skeleton2;
    private string _initSkinName = "A";
    private void ChangeBySkin(string slotName)
    {
        Skin dynamicSkin = _skeleton2.Data.FindSkin(_initSkinName);
        ExposedList<Slot> slots = _skeleton2.Slots;
        for (int i = 0, n = slots.Count; i < n; i++)
        {
            Slot slot = slots.Items[i];
            if (slot.Data.Name == slotName + "_A")
            {
                Attachment attachment = LGetAttachment(i, slotName, "B");
                if (attachment != null)
                {
                    slot.Attachment = attachment;
                    break;
                }
            }
        }
        _skeleton2.Skin = dynamicSkin;
    }

    public Attachment LGetAttachment(int slotIndex, string slotName, string skinName)
    {
        var targetSkin = _skeleton2.Data.FindSkin(skinName);
        var attachments = targetSkin.Attachments;

        Attachment attachment = null;
        foreach (var kv in attachments)
        {
            if (kv.Value.Name == slotName + "_B")
            {
                attachment = kv.Value;
                break;
            }
        }
        return attachment;
    }
    #endregion
}
